/*************************************************************************
    > File Name: Devices.c
	> Author: xuwenlong
	> Mail: myxuan475@126.com 
	> Created Time: 2018年01月17日 星期三 12时03分16秒
 ************************************************************************/
#include "devices.h"
#include <stdio.h>
#include <sqlite3.h>
#include <utils/custom.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <utils/config.h>
#include <vector>
#include <dbms/status.h>
#include <dbms/devices.h>
#include <dbms/transports.h>
#include <dbms/models.h>
#include <dbms/acquire.h>

Devices::Devices()
{
}

Devices::~Devices()
{
}

DAS_RESULT Devices::getDeviceStatus(const Json::Value &params, Json::Value &result)
{
    if (params.isMember("id")) {
        S32 id = params["id"].asInt();

        status sta(id);

        Json::Value inner;
        inner["result"] = sta.istatus();
        inner["status"] = sta.ionoff();
        result["inner"] = inner;
    }
    else {
        devices devs(-1);
        if (!devs.FetchItems("id"))
            return DAS_DEVICENOTEXIST;
        vector<deviceinfo_t> list =
                devs.getdevices();
        for (int i = 0;i<list.size();i++) {
            const deviceinfo_t &di =
                    list.at(i);
            Json::Value dev;
            dev["id"] = di.id;
            status sta(di.id);
            dev["status"] = sta.istatus();
            result.append(dev);
        }
    }
    return DAS_SUCCESS;
}

DAS_RESULT Devices::getAcquireValues(
        const Json::Value &params,
        Json::Value& result)
{
    if (!params.isMember("id"))
        return DAS_INVALIDPARAMETER;
    S32 id = params["id"].asInt();

    Json::Value values = getAcquireData(id);

    for (int i = 0;i < values.size();i++) {
        const Json::Value& v = values[i];

        if (!v.isMember("acq") ||
                !v.isMember("value"))
            return DAS_SUCCESS;
        string acq = v["acq"].asString();
//        result[acq]["name"] = v["name"].asString();
        result[acq] = v["value"].asFloat();
    }

    return DAS_SUCCESS;
}

DAS_RESULT Devices::getChnList(Json::Value &result)
{
    map<string,string> maplist;
    utils::GetSectionList("COM",maplist);

    for (map<string,string>::iterator iter=maplist.begin();
         iter!=maplist.end();iter++) {
        const string chn = iter->first;
//        result.append(chn);
        transports trans(-1);
        transmgr_t  tr = trans.gettransport_by_chn(chn);
        Json::Value com;
        com["chn"] = chn;
        com["communication"] = getCommunication(tr);
        result.append(com);
    }

    transports trans(-1);
    transmgr_t  tr = trans.gettransport_by_chn("tcp");
    if (!tr.empty()) {
        Json::Value com;
        com["chn"] = "tcp";
        com["communication"] = getCommunication(tr);
        result.append(com);
        result.append("tcp");
    }
    return DAS_SUCCESS;
}

DAS_RESULT Devices::getTempList(Json::Value &result)
{
    models md(-1);
    if (!md.FetchItems())
        return DAS_NOINFO;
    vector<models::modelitem> listitems = md.modelItems();

    for (int i = 0;i < listitems.size();i++) {
        const models::modelitem &item = listitems.at(i);
        Json::Value mj;
        mj["id"] = item.id;
        mj["name"] = item.name;
        mj["temp"] = item.temp;
        result.append(mj);
    }
    return DAS_SUCCESS;
}

DAS_RESULT Devices::getDeviceList(const Json::Value &params,Json::Value& result)
{
    if (!params.isMember("chn"))
        return DAS_JSON_PARSEFAILD;

    if (params["chn"].asString() == "all" ) {
        map<string,string> maplist;
        utils::GetSectionList("COM",maplist);
        maplist.insert(std::pair<string,string>("tcp","tcp"));

        for (map<string,string>::iterator iter=maplist.begin();
             iter!=maplist.end();iter++) {
            const string chn = iter->first;
            Json::Value list;
            list["chn"] = chn;
            devices dev(-1);

            vector<deviceinfo_t> devlist =
                    dev.getdevices_by_chn(chn);
            for (int i = 0;i<devlist.size();i++) {
                const deviceinfo_t &devinfo = devlist.at(i);
                Json::Value jdev = getDeviceInfo(devinfo);
                list["devices"].append(jdev);
            }
            result.append(list);
        }
    }
    else {
        const string chn = params["chn"].asString();
        result["chn"] = chn;
        devices dev(-1);
        vector<deviceinfo_t> devlist =
                dev.getdevices_by_chn(chn);//按通道获取设备
        for (int i = 0;i<devlist.size();i++) {
            const deviceinfo_t &devinfo = devlist.at(i);
            Json::Value jdev = getDeviceInfo(devinfo);
            result["devices"].append(jdev);
        }
    }

    return DAS_SUCCESS;
}

DAS_RESULT Devices::getDeviceInfo(const Json::Value &params, Json::Value &result)
{
    if (!params.isMember("id"))
        return DAS_JSON_PARSEFAILD;
    S32 id = params["id"].asInt();

    devices dev(id);
    if (!dev.FetchItems("*"))
        return DAS_NOINFO;
    deviceinfo_t devinfo =
            dev.getdevice();
    result = getDeviceInfo(devinfo);

    return DAS_SUCCESS;
}

DAS_RESULT Devices::addDevice(const Json::Value &params)
{
    if (!params.isMember("id"))
        return DAS_JSON_PARSEFAILD;

    S32 id = params["id"].asInt();

    /*
     * 更新设备
     */
    devices dev(id);
    if (!dev.inorup(params["name"].asString(),
               params["devId"].asString(),
               params["modelId"].asInt(),
               params["type"].asInt(),
               params["comId"].asInt()
               ))
        return DAS_STOREERROR;

    return DAS_SUCCESS;
}

DAS_RESULT Devices::deleteDevice(const Json::Value &params)
{
    if (!params.isMember("id"))
        return DAS_JSON_PARSEFAILD;
    S32 id = params["id"].asInt();

    devices dev(id);
    dev.deletethis();

//    transports trans(id);
//    trans.deletethis();

    return DAS_SUCCESS;
}

DAS_RESULT Devices::modifyDevice(const Json::Value &params)
{
    /*
     * 获取配置
     */
    return addDevice(params);
}

DAS_RESULT Devices::getAcquireData(const Json::Value &params, Json::Value &result)
{
    if (!params.isMember("model"))
        return DAS_INVALID;
    S32 model_id = params["model"].asInt();
    acquire aq(model_id);

    aq.FetchItems();

    vector<acquire::acquiredata>& list=aq.getAcqParams();

    Json::Value acquireDatas;
    for (int i = 0;i < list.size();i++) {
        Json::Value acqData;
        acquire::acquiredata& data = list.at(i);

        acqData["acqid"] = acquire::idToStr(data.itemId);
        acqData["dot"] = data.itemDot;
        acqData["name"] = data.itemName;
        acqData["reglen"] = data.reglen;
        acqData["expr"] = data.dataexpr;
        acqData["rate"] = data.fRate;

        string listparams;
        for (int j=0;j<data.listparams.size();j++) {
            listparams +=data.listparams[j];
            if (j!=data.listparams.size()-1)
                listparams += ";";
        }
        acqData["params"] = listparams;
        acquireDatas.append(acqData);
    }
    result["acquireData"] = acquireDatas;

    models md(model_id);
    result["template"] = md["template"];
    return DAS_SUCCESS;
}

Json::Value Devices::getDeviceInfo(const deviceinfo_t &dev)
{
    Json::Value jdev;
    jdev["id"] = dev.id;
    jdev["name"]=dev.name;
    jdev["code"] = dev.code;
    jdev["devId"]=dev.dev_id.c_str();
    status sta(dev.id);
    jdev["status"]= sta.istatus();
    jdev["sample"] = dev.trans.sample;//sample
    Json::Value jm;
    jm["id"] = dev.model_id;

    models mod(dev.model_id);
    jm["name"] = mod["name"];
    jdev["model"]= jm;
    jdev["type"] = dev.dev_type;
//    status sta(id);
    jdev["acquire"] = getAcquireData(dev.id);

    jdev["communication"] = getCommunication(dev.trans);
    return jdev;
}

transmgr_t Devices::getCommunication(const Json::Value &jsonTrans)
{
    transmgr_t trans;

    if (!jsonTrans.isMember("mode"))
        return trans;
    if (!strcmp(jsonTrans["mode"].asCString(),"serial")) {
        trans.trans_mode = TM_SEARIAL;
        Json::Value jsonAddr = jsonTrans["addr"];
        strcpy(trans.trans_addr.portaddr.com,jsonAddr["chn"].asCString());
        trans.trans_addr.portaddr.baudrate = jsonAddr["baudRate"].asInt();
        trans.trans_addr.portaddr.databit = jsonAddr["dataBits"].asInt();
        trans.trans_addr.portaddr.stopbit = jsonAddr["stopBits"].asInt();
        trans.trans_addr.portaddr.parity = jsonAddr["parity"].asInt();
    }
    else if (!strcmp(jsonTrans["mode"].asCString(),"tcp")){
        trans.trans_mode = TM_TCP;
        const Json::Value &jsonAddr = jsonTrans["addr"];
        strcpy(trans.trans_addr.socketaddr.ip_addr,jsonAddr["ip"].asCString());
        trans.trans_addr.socketaddr.port=jsonAddr["port"].asInt();
    }
    trans.timeout = jsonTrans["delay"].asInt();
    return trans;
}

Json::Value Devices::getAcquireData(S32 id)
{
    Json::Value result;
    status sta(id);
    string acqdata = sta.iacqdata();

    Json::CharReaderBuilder builder;
    builder["collectComments"] = false;
    Json::CharReader *reader = builder.newCharReader();

    const char *acqstr = acqdata.c_str();
    int length = acqdata.length();
    if (length == 0)
        return result;
    string err;
    if (!reader->parse(acqstr,acqstr+length,&result,&err)) {
        LOG_ERR("acqdata format error");
        delete reader;
        return result;
    }
    delete reader;
    return result;
}

Json::Value Devices::getCommunication(const transmgr_t &trans)
{
    Json::Value communication;
    if (trans.trans_mode == TM_TCP){
        communication["mode"] = "tcp";
        Json::Value addr;
        addr["ip"]=trans.trans_addr.socketaddr.ip_addr;
        addr["port"]=trans.trans_addr.socketaddr.port;
        communication["addr"]=addr;
        communication["delay"] = trans.timeout;
        communication["sample"] = trans.sample;
        communication["id"] = trans.id;
    }
    else if(trans.trans_mode == TM_SEARIAL){
        communication["mode"] = "serial";
        Json::Value addr;
        addr["chn"]=trans.trans_addr.portaddr.com;
        addr["baudRate"]=trans.trans_addr.portaddr.baudrate;
        addr["dataBits"]=trans.trans_addr.portaddr.databit;
        addr["parity"]=trans.trans_addr.portaddr.parity;
        addr["stopBits"]=trans.trans_addr.portaddr.stopbit;
        communication["addr"]=addr;
        communication["delay"] = trans.timeout;
        communication["sample"] = trans.sample;
        communication["id"] = trans.id;
    }

    return communication;
}
